package common

import (
	"context"
	"database/sql/driver"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/goravel/framework/facades"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

type Meta struct {
	Title       string  `json:"title"`
	Icon        string  `json:"icon"`
	Isext       bool    `json:"isExt"`
	ExtOpenMode int64   `json:"extOpenMode"`
	Type        int64   `json:"type"`
	OrderNo     int64   `json:"orderNo"`
	Show        int64   `json:"show"`
	ActiveMenu  *string `json:"activeMenu"`
	Status      int64   `json:"status"`
	keepAlive   int64   `json:"keepAlive"`
}

type IDs []int

func (t *IDs) Scan(value interface{}) error {
	bytesValue, _ := value.([]byte)
	return json.Unmarshal(bytesValue, t)
}

func (t IDs) Value() (driver.Value, error) {
	return json.Marshal(t)
}

func (t *Meta) Scan(value interface{}) error {
	bytesValue, _ := value.([]byte)
	return json.Unmarshal(bytesValue, t)
}

func (t Meta) Value() (driver.Value, error) {
	return json.Marshal(t)
}

type Album []string

func (t *Album) Scan(value interface{}) error {
	bytesValue, _ := value.([]byte)
	return json.Unmarshal(bytesValue, t)
}

func (t Album) Value() (driver.Value, error) {
	return json.Marshal(t)
}

type Param struct {
	Name  string `json:"name"`
	Value string `json:"value"`
}
type Swipers []string
type Videos []string
type Params []Param
type Keyword []string

func (t *Swipers) Scan(value interface{}) error {
	bytesValue, _ := value.([]byte)
	return json.Unmarshal(bytesValue, t)
}

func (t Swipers) Value() (driver.Value, error) {
	return json.Marshal(t)
}
func (t *Params) Scan(value interface{}) error {
	bytesValue, _ := value.([]byte)
	return json.Unmarshal(bytesValue, t)
}

func (t Params) Value() (driver.Value, error) {
	return json.Marshal(t)
}

func (t *Videos) Scan(value interface{}) error {
	bytesValue, _ := value.([]byte)
	return json.Unmarshal(bytesValue, t)
}

func (t Videos) Value() (driver.Value, error) {
	return json.Marshal(t)
}

func (t *Keyword) Scan(value interface{}) error {
	bytesValue, _ := value.([]byte)
	return json.Unmarshal(bytesValue, t)
}

func (t Keyword) Value() (driver.Value, error) {
	return json.Marshal(t)
}

// 地图位置
type Coordinates struct {
	Longitude float64 `json:"longitude"`
	Latitude  float64 `json:"latitude"`
}

type CoordRes struct {
	Type        string    `json:"type"`
	Coordinates []float64 `json:"coordinates"`
}

func (c CoordRes) GormDataType() string {
	return "geometry"
}

// GormValue 根据坐标数据生成 SQL 表达式
func (c CoordRes) GormValue(ctx context.Context, db *gorm.DB) clause.Expr {
	//如果c为nil,返回nil
	if c.Coordinates == nil {
		//赋值为nil
		return clause.Expr{SQL: "NULL", Vars: []interface{}{}}
	}

	// 生成 SQL 表达式
	return clause.Expr{
		SQL:  "ST_GeomFromText(?,4326)",
		Vars: []interface{}{fmt.Sprintf("POINT(%.15f %.15f)", c.Coordinates[1], c.Coordinates[0])},
	}
}

// Scan 方法实现了 sql.Scanner 接口，用于从数据库中扫描和解码坐标数据
func (c *CoordRes) Scan(value interface{}) error {
	if value == nil {
		return nil
	}
	bytes, ok := value.([]byte)
	if !ok {
		return errors.New("invalid value type, expected []byte")
	}
	if len(bytes) == 0 {
		c = nil
		return nil
	}

	var coordRes string
	querySql := "SELECT ST_AsGeoJSON(?) as coord"
	param := string(bytes)
	facades.Orm().Query().Raw(querySql, param).Pluck("coord", &coordRes)
	err := json.Unmarshal([]byte(coordRes), c)
	return err
}

type Assign struct {
	UserID int     `form:"user_id" json:"user_id"`
	Score  float64 `form:"score" json:"score"`
}
type ScoreAssign []Assign

func (t ScoreAssign) Value() (driver.Value, error) {
	return json.Marshal(t)
}

func (t *ScoreAssign) Scan(value interface{}) error {
	bytesValue, _ := value.([]byte)
	return json.Unmarshal(bytesValue, t)
}
